#ifndef LEXICON_H
#define LEXICON_H
#include<cstddef>
#include<vector>
#include<string>
#include<iostream>
using std::string;
using std::vector;
using std::ostream;
using std::endl;
class Lexicon
{
    private:
    unsigned short* postingfid;
    int* docfq;
    size_t* startbyte;
    size_t* bytenum;
    int len;
    public:
    Lexicon(int vwsize = LEXICON_SIZE)
    {
        cout << " lexicon constructor " << endl;
        postingfid = new unsigned short[vwsize];
        for(int i=0; i<vwsize; ++i)
        postingfid[i] = -1;
        docfq = new int[vwsize];
        startbyte = new size_t[vwsize];
        bytenum = new size_t[vwsize];
        len = 0;
    }
    ~Lexicon()
    {
        cout << " lexicon destructor " << endl;
    }
    void push(unsigned short _postingfid,int _docfq,size_t _startbyte,size_t _bytenum)
    {
        postingfid[len] = _postingfid;
        docfq[len] = _docfq;
        startbyte[len] = _startbyte;
        bytenum[len] = _bytenum;
        ++len;
    }
    void free()
    {
        delete[] postingfid;
        delete[] docfq;
        delete[] startbyte;
        delete[] bytenum;
    }
    void fromfile(string filename)
    {
        cout << " read lexicon from file " << filename << endl;
        struct stat statbuf;
        stat(filename.c_str(),&statbuf);
        int fid = open(filename.c_str(),O_RDONLY);
        char *back_buf = reinterpret_cast<char*>(mmap(NULL,statbuf.st_size,PROT_READ,MAP_PRIVATE,fid,0));
        len = *(reinterpret_cast<int*>(back_buf));
        char* buf = back_buf + sizeof(int);
        size_t step = sizeof(unsigned short) * len;
        memcpy(postingfid,buf,step);
        buf += step;
        step = sizeof(int) * len;
        memcpy(docfq,buf,step);
        buf += step;
        step = sizeof(size_t) * len;
        memcpy(startbyte,buf,step);
        buf += step;
        memcpy(bytenum,buf,step);
        munmap(back_buf,statbuf.st_size);
        close(fid);
    }
    void tofile(string filename)
    {
        cout << " write lexicon to file " << filename <<endl;
        FILE* fid = fopen(filename.c_str(),"w");
        fwrite(reinterpret_cast<char*>(&len),sizeof(int),1,fid);
        fwrite(reinterpret_cast<char*>(postingfid),sizeof(unsigned short),len,fid);
        fwrite(reinterpret_cast<char*>(docfq),sizeof(int),len,fid);
        fwrite(reinterpret_cast<char*>(startbyte),sizeof(size_t),len,fid);
        fwrite(reinterpret_cast<char*>(bytenum),sizeof(size_t),len,fid);
        fclose(fid);
    }
    int length()
    {
        return len;
    }
    unsigned short get_postingfid(int i)
    {
        return postingfid[i];
    }
    int get_docfq(int i)
    {
        return docfq[i];
    }
    size_t get_startbyte(int i)
    {
        return startbyte[i];
    }
    size_t get_bytenum(int i)
    {
        return bytenum[i];
    }
    friend ostream& operator <<(ostream&, Lexicon&);
};
ostream& operator <<(ostream& os,Lexicon& lex)
{
    os << " total " << lex.len << " visual words " << endl;
    for(int i=0; i<lex.len; ++i)
    {
        os << " dataid = " << lex.postingfid[i];
        os << " docfq = " << lex.docfq[i];
        os << " startbyte = " << lex.startbyte[i];
        os << " bytenum = " << lex.bytenum[i];
        os << endl;
    }
    return os;
}
#endif
